package main.java.maziacs;

import java.io.*;

import main.java.maziacs.characters.Battle;
import main.java.maziacs.characters.IHero;
import main.java.maziacs.characters.Maziacs;
import main.java.maziacs.characters.Position;
import main.java.maziacs.counters.Counter;
import main.java.maziacs.counters.Food;
import main.java.maziacs.counters.Prisoner;
import main.java.maziacs.counters.Sword;
import main.java.maziacs.counters.Treasure;
import main.java.maziacs.squares.EndSquare;
import main.java.maziacs.squares.ICircle;
import main.java.maziacs.squares.ISquare;
import main.java.maziacs.squares.IWhite;
import main.java.maziacs.squares.Square;
import main.java.maziacs.squares.White;

public class UI implements IUI{

	/**
	 * @uml.property  name="game"
	 * @uml.associationEnd  inverse="uI:uml.Game"
	 */
	private IGame game;

	
	public UI(IGame game){
		setGame(game);
	}
	/* (non-Javadoc)
	 * @see uml.IUI#getGame()
	 */
	public IGame getGame() {
		return game;
	}

	/* (non-Javadoc)
	 * @see uml.IUI#setGame(uml.Game)
	 */
	public void setGame(IGame game) {
		this.game = game;
	}

	/* (non-Javadoc)
	 * @see uml.IUI#choosePutTile(uml.ITile, uml.ITile)
	 */
	public void choosePutTile(ITile tile1, Square sq1, ITile tile2){
		if(tile1.equals(null) || tile2.equals(null))
			throw new IllegalArgumentException();
		String s="";
		ISquare sq2=new Square(tile2);
				System.out.println("Indique el lado de la loseta nueva que sera adyacente con la antigua loseta\n" +
				"teniendo en cuenta que solo seran validos aquellos lados que tengan una casilla blanca," +
				"es decir que no ponga X:\n" +
				tile2.toString() + 
				"- Arriba(U)\n" + "- Abajo(D)\n" + "- Izquierda(L)\n" + "- Derecha(R)\n");
		s="";
		try{
			/*
			 * Se comprueba que el jugador elige una posicion valida*/
			while(!((s.equals("U") && tile2.getSquares()[0][1] instanceof IWhite) || 
					(s.equals("D") && tile2.getSquares()[2][1] instanceof IWhite) ||
					(s.equals("L") && tile2.getSquares()[1][0] instanceof IWhite) || 
					(s.equals("R") && tile2.getSquares()[1][2] instanceof IWhite))){
				BufferedReader br= new BufferedReader(new InputStreamReader(System.in));
				s=br.readLine();
				if((s.equals("U") && !(tile2.getSquares()[0][1] instanceof IWhite)) || 
						(s.equals("D") && !(tile2.getSquares()[2][1] instanceof IWhite)) ||
						(s.equals("L") && !(tile2.getSquares()[1][0] instanceof IWhite)) || 
						(s.equals("R") && !(tile2.getSquares()[1][2] instanceof IWhite)))
					System.out.println("Por favor introduzca:\n" +
							"U para Arriba\n" + "D para Abajo\n" + "L para la Izquierda\n" +
									"R para la Derecha\n" + "asegurandose de que la opcion elegida es valida," +
											"es decir, en ese lado hay una casilla blanca");
			}
		}catch (Exception e) {
			e.printStackTrace();
		}
		/*
		 * Segun la posicion elegida , se establece la posicion de la casilla por la que
		 * van a ser adyacentes*/
		if(s.equals("U")){
			sq2.setPositionI(0);
			sq2.setPositionJ(1);
		}
		else if(s.equals("D")){
			sq2.setPositionI(2);
			sq2.setPositionJ(1);
		}
		else if(s.equals("L")){
			sq2.setPositionI(1);
			sq2.setPositionJ(0);
		}
		else if(s.equals("R")){
			sq2.setPositionI(1);
			sq2.setPositionJ(2);
		}
		/*Se coloca la loseta en el tablero*/
		game.getBoard().putTile(tile1, sq1, tile2, sq2);
	}

	/*Deja un contador en una casilla circular*/
	private void leaveCounter(IHero hero, ICircle s){
		String linea="";
		
			System.out.println("Deseas dejar el contador en la casilla circular\n");
			System.out.println("SI/NO\n");
			try{
			/*Se comprueba que se elije una opcion valida*/
				while(!linea.equals("SI") && !linea.equals("NO")){
					BufferedReader br=new BufferedReader(new InputStreamReader(System.in));
					linea=br.readLine();
					if(!linea.equals("SI") && !linea.equals("NO")){
						System.out.println("Diga SI o NO");
					}
				}
			}catch(Exception e){
				e.printStackTrace();
			}
			/*Al dejar el contador, si es una espada se suelta la espada y si
			 * habia un tesoro se coje el tesoro y viceversa*/
			if(linea.equals("SI")){
				Counter c=null;
				if(hero.hasSword()){
					c=new Sword(s.getTile().getBoard().getBag());
					hero.setSword(false);
				}
				if(hero.hasTreasure()){
					c=hero.getTTreasure();
					hero.setTTreasure(null);
					hero.setTreasure(false);
				}
				s.setCounters(c);
			}
	}

	/*Se coje un contador de una casilla circular*/
	private void takeCounter(IHero hero, ICircle s){
		String linea="";
		String tipo="";
		// Se dice de que tipo es el contador
		if(s.getCounters() instanceof Food)
			tipo="El contador es Comida\n";
		else if(s.getCounters() instanceof Sword)
			tipo="El contador es una Espada\n";
		else if(s.getCounters() instanceof Treasure)
			tipo="El contador es el Tesoro\n";
		else if(s.getCounters() instanceof Prisoner)
			tipo="El contador es un Prisionero\n";
		
		System.out.println(tipo + "Deseas coger el contador de la casilla circular\n");
		System.out.println("SI/NO\n");
		try{
		/*Se comprueba que se elije una opcion valida*/
			while(!linea.equals("SI") && !linea.equals("NO")){
				BufferedReader br=new BufferedReader(new InputStreamReader(System.in));
				linea=br.readLine();
				if(!linea.equals("SI") && !linea.equals("NO")){
					System.out.println("Diga SI o NO");
				}
			}
		}catch(Exception e){
			e.printStackTrace();
		}
		/*En caso de querer coger el contador se actua en funcion de que tipo de contador sea
		 * teniendo en cuenta que si es espada o tesoro, se suelta el que se llevase encima*/
		if(linea.equals("SI")){
			if(s.getCounters() instanceof Food){
				hero.setEnergy(20);
				s.setCounters(null);
			}
			if(s.getCounters() instanceof Prisoner){
				hero.askPrisoner(s.getCounters());
				hero.setPrisoners(hero.getPrisoners()+1);
			}
			if(s.getCounters() instanceof Sword){
				hero.setSword(true);
				if(hero.hasTreasure()){
					hero.setTreasure(false);
				}
			}
			if(s.getCounters() instanceof Treasure){
				hero.setTreasure(true);
				hero.setTTreasure((Treasure)s.getCounters());
				if(hero.hasSword())
					hero.setSword(false);
			}
		}
	}
	
	/* (non-Javadoc)
	 * @see uml.IUI#chooseTakeOrLeaveCounter(uml.IHero)
	 */
	public void chooseTakeOrLeaveCounter(IHero hero){
		//Obtenemos la posision del heroe.
		White w=(White)hero.getPosition().getSquare();
		ICircle c=null;
		//Se comprueba que es adyacente a una casilla circulo.
		if(w.AdjacentToCircle())
				c=w.getCircleAdjacent();
				//Si esla casilla final.
			if(c instanceof EndSquare){
				c=(EndSquare)c;
			}
		//Si no hay un contador lo dejamos
		//Si lo hay, lo intercambiamos por el que tengamos en nuestro poder 
		if(c!=null && c.getCounters().equals(null) && (hero.hasSword() || hero.hasTreasure())){
			leaveCounter(hero, c);
		}
		//Si hay un contador lo cogemos.
		if(c!=null && !c.getCounters().equals(null)){
			takeCounter(hero, c);
		}
	}

	/* (non-Javadoc)
	 * @see uml.IUI#chooseSquareToMoveHero(uml.IHero)
	 */
	public void chooseSquareToMoveHero(IHero hero){
		ISquare s=hero.getPosition().getSquare();
		Integer num=0;
		/*Mostramos para que el usuario elija, las casillas a las que el heroe puede moverse*/
		System.out.println("Escoja la casilla a la que desea moverse:\n");
		Integer i=1;
		for(ISquare square: s.getAdjacentSquares()){
			System.out.println(i+ ".- (" + square.getPositionI() + 
					", " + square.getPositionJ() + ") en la loseta " + square.getTile().getName() + "\n");
			i++;
		}
		String linea="";
		try{
			/*El usuario solo puede moverse a una de las casillas de entre
			 * las adyacentes a la casilla en la que se encuentra en ese momento*/
			while(num!=1 && num!=2 && num!=3 && num!=4 ){
				BufferedReader br=new BufferedReader(new InputStreamReader(System.in));
				linea=br.readLine();
				num=new Integer(linea);
				if(num.compareTo(s.getAdjacentSquares().size())>0){
					num=0;
					System.out.println("Escoja una opcion valida\n");
				}
			}
		}catch(Exception e){
			e.printStackTrace();
		}
		/*Almacenamos la posicion anterior del heroe*/
		hero.setLastPosition(hero.getPosition());
		/*Modificamos la posicion del heroe*/
		hero.setPosition(new Position(s.getAdjacentSquares().get(num-1).getTile(), 
				s.getAdjacentSquares().get(num-1)));
		/*Comprobamos si hemos llegado a la casilla de algun maziac y luchamos entonces*/
		for (Maziacs m: hero.getBoard().getMaziacs().keySet()){
			@SuppressWarnings("unused")
			Battle b;
			if(m.calculateDistance(hero)==0){
				b=new Battle(hero,m);
			}
		}
		//Miramos si la loseta anterior es la misma que la actual, y si son distintas,
		//llamamos a putGem() para ver si es necesario y si se puede poner una gema
		if(!hero.getPosition().getTile().equals(hero.getLastPosition().getTile()) &&
				//!hero.getLastPrisoner().equals(null)){
				hero.getPrisoners()>0){
			hero.getLastPrisoner().setHero(hero);
			hero.askPrisoner(hero.getLastPrisoner());
			hero.setPrisoners(hero.getPrisoners()+1);
			hero.putGem();
		}
		White w=(White)hero.getPosition().getSquare();
		if(hero.hasTreasure() && w.containGem())
			hero.takeGem(w);
		hero.explore();
	}
					
	/* (non-Javadoc)
	 * @see uml.IUI#chooseActionWithMaziac(uml.IHero)
	 */
	public void chooseActionWithMaziac(IHero hero){
		String s="";
		Dice dice=new Dice(6);
		/*Se determinan el numero de acciones que tendra el heroe*/
		Integer throwDice=dice.rollingDice();
		White w=(White)hero.getPosition().getSquare();
		for (int i=0;i<throwDice;i++){
			ICircle c=null;
			Boolean circle=false;
				if(w.AdjacentToCircle()){
					c=w.getCircleAdjacent();
					circle=true;
				}
			/*Se comprueba si hay casilla circular adyacente para poder dar la opcion
			 * de coger o dejar un objeto en la casilla circular o no*/
			if(circle){
				if(hero.hasSword())
					System.out.println("Tienes espada\n");
				else
					System.out.println("No tienes espada\n");
				System.out.println("Elija una de las siguientes opciones:\n");
				System.out.println("1.- Moverse un paso en cualquier direccion legal\n");
				System.out.println("2.- Coger o dejar un objeto en una casilla circular adyacente\n");
				if(!c.equals(null) && c.getCounters() instanceof Prisoner){
					System.out.println("3.- Preguntar por el camino correcto a un prisionero\n");
				}
				
				try{
					/*
					 * Se comprueba que se elige una accion valida*/
					while((!s.equals("1") && !s.equals("2") && !s.equals("3"))
							|| (s.equals("3") && c.equals(null))){
						BufferedReader br=new BufferedReader(new InputStreamReader(System.in));
						s=br.readLine();
						if((!s.equals("1") && !s.equals("2") && !s.equals("3"))
								|| (s.equals("3") && c.equals(null)))
							System.out.println("Introduzca una opcion valida\n");
					}
				}catch (Exception e) {
					e.printStackTrace();
				}
				/*Se llama al metodo apropiado segun la accion elegida*/
				if(s.equals("1")){
					chooseSquareToMoveHero(hero);
				}
				else if(s.equals("2")){
					chooseTakeOrLeaveCounter(hero);				
				}
				else if(s.equals("3") && !c.equals(null)){
					hero.askPrisoner(c.getCounters());
					hero.setPrisoners(hero.getPrisoners()+1);
				}
			}
			else{
				System.out.println("Elija una de las siguientes opciones:\n");
				System.out.println("1.- Moverse un paso en cualquier direccion legal\n");
				if(!c.equals(null)){
					if(c.getCounters() instanceof Prisoner)
						System.out.println("2.- Preguntar por el camino correcto a un prisionero\n");
				}
				try{
					/*
					 * Se comprueba que se elige una accion valida*/
					while((!s.equals("1") && !s.equals("2")) || (s.equals("2") && c.equals(null))){
						BufferedReader br=new BufferedReader(new InputStreamReader(System.in));
						s=br.readLine();
						if((!s.equals("1") && !s.equals("2")) || (s.equals("2") && c.equals(null)))
							System.out.println("Introduzca una opcion valida\n");
					}
				}catch (Exception e) {
					e.printStackTrace();
				}
				/*Se llama al metodo apropiado segun la accion elegida*/
				if(s.equals("1")){
					chooseSquareToMoveHero(hero);
				}
				else if(s.equals("2") && !c.equals(null)){
					hero.askPrisoner(c.getCounters());
					hero.setPrisoners(hero.getPrisoners()+1);
				}
			}
		}
	}

	/**
	 * @uml.property  name="player"
	 */
	private int player;

	/* (non-Javadoc)
	 * @see uml.IUI#getPlayer()
	 */
	public int getPlayer() {
		return player;
	}

	/* (non-Javadoc)
	 * @see uml.IUI#setPlayer(int)
	 */
	public void setPlayer(int player) {
		this.player = player;
	}

						
							
							
	/* (non-Javadoc)
	 * @see uml.IUI#chooseDifficultyLevel()
	 */
	public Level chooseDifficultyLevel(){
		Level lvl=null;
		Integer num=0;
		String linea="";
		System.out.println("Introduzca el nivel de dificultad\n");
		System.out.println("1. Facil\n2. Medio\n3. Dificil");
		try{
			/*Se comprueba que se elige un nivel de dificultad valido y se establece ese nivel*/
			while(num!=1 && num!=2 && num!=3){
				BufferedReader br=new BufferedReader(new InputStreamReader(System.in));
				linea=br.readLine();
				num=new Integer(linea);
				if(num!=1 && num!=2 && num!=3)
					System.out.println("Nivel de dificultad erroneo, introduzca un nivel entre 1 y 3\n");
				else
					lvl=new Level(num);
			}
		}catch (Exception e) {
			e.printStackTrace();
		}
		return lvl;
	}
							
							
	/* (non-Javadoc)
	 * @see uml.IUI#chooseNumberOfGamers()
	 */
	public Integer chooseNumberOfGamers(){
		Integer num=0;
		String linea="";
		System.out.println("Introduzca el numero de jugadores de la partida:\n");
		try{
			while(num!=1 && num!=2){
				BufferedReader br=new BufferedReader(new InputStreamReader(System.in));
				linea=br.readLine();
				num=new Integer(linea);
				if(num!=1 && num!=2)
					System.out.println("La partida no puede tener mas de 2 jugadores, introduzca el numero de jugadores:\n");
			}
		}catch (Exception e) {
			e.printStackTrace();
		}
		return num;
	}

}
